package cc.rengu.igas.channel.cups.core.service.trans;


import cc.rengu.igas.channel.cups.common.constant.CupsConfigConstant;
import cc.rengu.igas.channel.cups.common.constant.CupsParamConstant;
import cc.rengu.igas.channel.cups.common.constant.CupsTreeNodeConstant;
import cc.rengu.igas.channel.cups.common.enums.RespCodeEnum;
import cc.rengu.igas.channel.cups.core.model.ChnlBizResponse;
import cc.rengu.igas.channel.cups.core.model.CupsFieldRspBean;
import cc.rengu.igas.channel.cups.core.realize.CupsMacService;
import cc.rengu.igas.channel.cups.core.realize.impl.CupsMacServiceImpl;
import cc.rengu.igas.channel.cups.core.service.base.BaseCancelService;
import cc.rengu.igas.channel.cups.facade.request.TransferOutCancelRequest;
import cc.rengu.igas.channel.cups.facade.response.TransferOutCancelResponse;
import cc.rengu.igas.share.facade.bean.CupsField;
import cc.rengu.igas.share.facade.bean.CupsFieldBean;
import cc.rengu.jradp.mods.trmsg.iso8583.MacUtil;
import cc.rengu.jradp.schedule.ScheduleImpl;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.entity.DstChannelInfo;
import cc.rengu.oltp.service.common.entity.KeyInfo;
import cc.rengu.oltp.service.common.entity.SysParam;
import cc.rengu.oltp.service.common.enums.OltpRpcdEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.realize.SysParamService;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.util.AmountUtil;
import cc.rengu.oltp.utility.util.BeanUtil;
import cc.rengu.oltp.utility.util.ConvertUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;
import cc.rengu.utility.cache.UnifiedCache;

/**
 * 转账转出撤销
 *
 * @author Administrator
 */
public class CupsTransferOutCancelService extends BaseCancelService<TransferOutCancelRequest, TransferOutCancelResponse> {

    @Override
    protected TransferOutCancelRequest beforeBizProcess() throws Exception {
        TransferOutCancelRequest transferOutCancelRequest = new TransferOutCancelRequest();
        ConvertUtil.convertOutput(transferOutCancelRequest);
        return transferOutCancelRequest;
    }

    @Override
    protected ChnlBizResponse<TransferOutCancelResponse> callBizService(TransferOutCancelRequest transferOutCancelRequest) throws Exception {
        return directCups(transferOutCancelRequest);
    }

    @Override
    protected void afterBizProcess(ChnlBizResponse<TransferOutCancelResponse> response) throws Exception {
        TransferOutCancelResponse transferOutCancelResponse = response.getResult();
        ConvertUtil.convertInput(transferOutCancelResponse);
    }

    /**
     * 直连cups
     *
     * @param transferOutCancelRequest 转出请求
     * @return 应答
     * @throws Exception 失败
     */
    ChnlBizResponse<TransferOutCancelResponse> directCups(TransferOutCancelRequest transferOutCancelRequest) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        int iReturnCode = 0;
        String algorithm = null;
        ChnlBizResponse<TransferOutCancelResponse> chnlBizResponse = new ChnlBizResponse<>();
        TransferOutCancelResponse transferOutCancelResponse = new TransferOutCancelResponse();
        String instId = transferOutCancelRequest.getHeader().getInstId();
        DstChannelInfo dstChannelInfo = (DstChannelInfo) xmlTreeUtil.getXmlTreeObjectValue(CupsTreeNodeConstant.DST_CHANNEL_INFO, DstChannelInfo.class);
        SysParamService sysParamService = new SysParamServiceImpl();
        SysParam sysParam = sysParamService.getSysParamInfo(instId,
                CupsConfigConstant.CUPS_CONF_NODE, CupsConfigConstant.CUPS_ALG_TYPE);
        if (sysParam != null) {
            algorithm = sysParam.getParamValue();
        }
        CupsFieldBean cupsFieldBean = new CupsFieldBean();
        ConvertUtil.convertOutput(cupsFieldBean);
        CupsField cupsField = cupsFieldBean.getCupsField();
        BeanUtil.beanCopy(transferOutCancelRequest, cupsField);
        cupsField.setMsgType("0200");
        cupsField.setProcCode("480000");
        cupsField.setConCode("12");

        cupsField.setTransDateTime(transferOutCancelRequest.getTransDateTime());
        cupsField.setLocalDate(transferOutCancelRequest.getTransDateTime().substring(0, 4));
        cupsField.setLocalTime(transferOutCancelRequest.getTransDateTime().substring(4));
        cupsField.setEntryMode("012");
        String reseved = packF060Field("4021", transferOutCancelRequest.getTermRead(), transferOutCancelRequest.getIcConCode(),
                null, null, transferOutCancelRequest.getTermType(), algorithm, transferOutCancelRequest.getSettleCardFlag());
        cupsField.setReseved(reseved);
        String tmpAmt = AmountUtil.changeY2F(transferOutCancelRequest.getOrderAmt());
        cupsField.setOrderAmt(String.format("%012d", Integer.valueOf(tmpAmt)));
        xmlTreeUtil.setXmlTreeStringValue(CupsTreeNodeConstant.CUPS_MACBLOCK_ORIG_DATA_ELEMTS, cupsField.getOrigData().substring(0, 20));
        cupsFieldBean.setCupsField(cupsField);
        ConvertUtil.convertInput(cupsFieldBean);
        /*计算macblock*/
        MacUtil commonMac = (MacUtil) UnifiedCache.get(CupsParamConstant.CUPS_8583_MAC_CACHE_NAME,
                CupsParamConstant.CUPS_8583_MAC_FILE +
                        CupsParamConstant.CUPS_8583_MAC_TYPE_TA);
        byte[] macBlock = commonMac.genMacBlock(CupsParamConstant.CUPS_8583_MAC_TYPE_TA);
        if (macBlock == null) {
            throw new BizException(RespCodeEnum.GENERATE_MAC_BLOCK_ERROR.getRespCode(), RespCodeEnum.GENERATE_MAC_BLOCK_ERROR.getRespDesc());
        }
        xmlTreeUtil.setXmlTreeStringValue(CupsTreeNodeConstant.CUPS_MAC_BLOCK, new String(macBlock, CupsParamConstant.GB18030));
        String oriTxnNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TXN_NUM);
        xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TXN_NUM, transferOutCancelRequest.getHeader().getTxnNum());
        iReturnCode = schedule.callService(dstChannelInfo.getDstServiceName(), 0);
        if (ScheduleImpl.SERVICE_TIMEOUT == iReturnCode) {
            rglog.error("调用银联cups服务<{}>超时，iReturnCode:<{}>", dstChannelInfo.getDstServiceName(), iReturnCode);
            transferOutCancelResponse.setRespCode(OltpRpcdEnum.BIZ_PROCESS_TIMEOUT.getRespCode());
            transferOutCancelResponse.setRespDesc(OltpRpcdEnum.BIZ_PROCESS_TIMEOUT.getRespDesc());
            chnlBizResponse.setResult(transferOutCancelResponse);
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TXN_NUM, oriTxnNum);
            return chnlBizResponse;
        } else if (0 != iReturnCode) {
            rglog.error("调用银联cups服务<{}>失败，iReturnCode:<{}>", dstChannelInfo.getDstServiceName(), iReturnCode);
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TXN_NUM, oriTxnNum);
            throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
        }
        /*还原交易码*/
        xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TXN_NUM, oriTxnNum);
        String tunlSsn = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.CHANNEL_SEQ_NUM);
        UnifiedCache.remove(CupsParamConstant.CACHE_CUPS_SN, tunlSsn);

        CupsFieldRspBean cupsFieldRspBean = new CupsFieldRspBean();
        ConvertUtil.convertOutput(cupsFieldRspBean);
        String mac = cupsFieldRspBean.getCupsFieldRsp().getMac();
        /*生成应答macBlock*/
        byte[] macBlockRsp = commonMac.getMacBlock(CupsParamConstant.CUPS_8583_MAC_TYPE_TA);
        CupsMacService cupsMacService = new CupsMacServiceImpl();
        KeyInfo keyInfo = (KeyInfo) xmlTreeUtil.getXmlTreeObjectValue(CupsTreeNodeConstant.CUPS_MAC_KEY_INFO, KeyInfo.class);
        boolean flag = cupsMacService.verifyMacString(keyInfo, mac, new String(macBlockRsp, CupsParamConstant.GB18030));
        if (!flag) {
            rglog.error("验证mac失败");
            throw new BizException(RespCodeEnum.VERIFY_MAC_ERROR.getRespCode(), RespCodeEnum.VERIFY_MAC_ERROR.getRespDesc());
        }

        CupsField cupsFieldRsp = cupsFieldRspBean.getCupsFieldRsp();
        BeanUtil.beanCopy(cupsFieldRsp, transferOutCancelResponse);
        if (transferOutCancelResponse.getSettleDate() != null) {
            transferOutCancelResponse.setSettleDate(getCupsSettleDate(transferOutCancelResponse.getSettleDate()));
        }
        transferOutCancelResponse.setRespCode(cupsFieldRsp.getRespCode());
        if (CupsParamConstant.SUCCESS_CODE.equals(transferOutCancelResponse.getRespCode())) {
            transferOutCancelResponse.setRespCode(OltpRpcdEnum.TRANS_SUCCESS.getRespCode());
            transferOutCancelResponse.setRespDesc(OltpRpcdEnum.TRANS_SUCCESS.getRespDesc());
        }
        chnlBizResponse.setResult(transferOutCancelResponse);
        return chnlBizResponse;
    }

}
